﻿using System.Reflection;
using System.Text;
using LF.Application;
using LF.Application.Services;
using LF.Domain.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Server.IIS;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using Volo.Abp;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Autofac;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;

namespace LF.WebCore
{
    [DependsOn(typeof(AbpAspNetCoreMvcModule), typeof(AbpAutofacModule), typeof(AbpSwashbuckleModule), typeof(LFModule))]
    public class AppModule : AbpModule
    {
       
        string _orgins = "LFSpecificOrigins";
        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

#if DEBUG
            // Configure the HTTP request pipeline.
           
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
#endif

            if (LFConfig.Debug)
            {
                app.UseSwagger();
                app.UseSwaggerUI(options =>
                {
                    options.SwaggerEndpoint("/swagger/v1/swagger.json", "公共API");
                    options.SwaggerEndpoint($"/swagger/{SwaggerGroup.Sys}/swagger.json", "系统API");
                    options.SwaggerEndpoint($"/swagger/{SwaggerGroup.Ai}/swagger.json", "AI-API");
                    options.RoutePrefix = "apis";
                });
            }
               
            
            //app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
            #region 启用跨域
            app.UseCors(_orgins);
            #endregion
            app.UseAuthentication();
            app.UseAuthorization();
            
            // 在此处添加自定义中间件，在认证和授权之后
            app.Use(async (context, next) =>
            {
                // 在请求处理开始前，从HttpContext中获取当前用户ID，并赋值给DomainConfig.CurrentUserId
                // 尝试多种可能的Claim类型获取用户ID
                var userId = context.User?.Claims?.FirstOrDefault(c => 
                    c.Type == "Id" || 
                    c.Type == "sub" || 
                    c.Type == "nameid" ||
                    c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" ||
                    c.Type == "userId")?.Value;
                
                //// 手动调试JWT令牌
                //try 
                //{
                //    var authHeader = context.Request.Headers["Authorization"].FirstOrDefault();
                //    if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("Bearer "))
                //    {
                //        var token = authHeader.Substring("Bearer ".Length).Trim();
                //        Console.WriteLine($"手动解析令牌: {token}");
                        
                //        // 尝试手动解析JWT令牌
                //        var handler = new System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler();
                //        if (handler.CanReadToken(token))
                //        {
                //            var jwtToken = handler.ReadJwtToken(token);
                //            Console.WriteLine("手动解析JWT令牌成功");
                            
                //            foreach (var claim in jwtToken.Claims)
                //            {
                //                Console.WriteLine($"手动解析Claim: {claim.Type} = {claim.Value}");
                                
                //                // 如果找到Id声明，尝试使用它
                //                if (claim.Type == "Id" && Guid.TryParse(claim.Value, out Guid parsedId))
                //                {
                //                    Console.WriteLine($"从手动解析中找到Id: {parsedId}");
                //                    LF.Domain.DomainConfig.CurrentUserId = parsedId;
                //                }
                //            }
                //        }
                //        else
                //        {
                //            Console.WriteLine("无法读取JWT令牌，格式可能不正确");
                //        }
                //    }
                //    else
                //    {
                //        Console.WriteLine("未找到有效的Authorization Bearer令牌");
                //    }
                //}
                //catch (Exception ex)
                //{
                //    Console.WriteLine($"手动解析JWT令牌时出错: {ex.Message}");
                //}
                
                Console.WriteLine($"当前User Claims: {string.Join(", ", context.User?.Claims?.Select(c => $"{c.Type}={c.Value}") ?? Array.Empty<string>())}");

                if (!string.IsNullOrEmpty(userId) && Guid.TryParse(userId, out Guid guidUserId))
                {
                    Console.WriteLine($"成功获取到用户ID: {guidUserId}");
                    LF.Domain.DomainConfig.CurrentUserId = guidUserId;
                }
                else
                {
                    Console.WriteLine("未获取到有效的用户ID");
                    LF.Domain.DomainConfig.CurrentUserId = Guid.Empty;
                }

                await next();
            });
            
            app.UseConfiguredEndpoints();

            //// 初始化系统管理员账号
            //var appManagerService = context.ServiceProvider.GetRequiredService<IAppManagerService>();
            //appManagerService.InitializeSysAdmin();

            // 启动时扫描权限并维护到数据库
            var permissionScanner = context.ServiceProvider.GetRequiredService<IPermissionScannerService>();
            permissionScanner.ScanAndSavePermissions();
            
            // 初始化切片方式字典
            var dictManagerService = context.ServiceProvider.GetRequiredService<IDictManagerService>();
            dictManagerService.InitializeSliceTypeDict();

            // 初始化默认参数配置
            var paramConfigManager = context.ServiceProvider.GetRequiredService<IParamConfigManagerService>();
            paramConfigManager.InitializeDefaultParams();

#if !DEBUG
            context.GetLoggerFactory().CreateLogger("WEB").LogWithLevel(LogLevel.Warning, "WEB 启动完成：" + context.GetConfiguration()["url"]);
#endif
        }

        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var services = context.Services;
            var config = services.GetConfiguration();
            var debug = config.GetValue<bool>("debug");
            LFConfig.Debug = debug;
            #region swagger
            if (LFConfig.Debug)
            { 
                services.AddAbpSwaggerGen(
                options =>
                {
                    options.HideAbpEndpoints();

                    const string nomarl = "v1";
                    options.SwaggerDoc(nomarl, new OpenApiInfo { Title = "公共API", Version = "v1" });
                    options.SwaggerDoc(SwaggerGroup.Sys, new OpenApiInfo { Title = "系统API", Version = "v1" });
                    options.SwaggerDoc(SwaggerGroup.Ai, new OpenApiInfo { Title = "AI-API", Version = "v1" });

                    options.DocInclusionPredicate((docName, description) => {
                        if (!description.TryGetMethodInfo(out MethodInfo method))
                        {
                            return false;
                        }
                        //隐藏ABP默认API
                        if (method.DeclaringType!.Name.StartsWith("Abp"))
                        {
                            return false;
                        }
                        //使用ApiExplorerSettingsAttribute里面的GroupName进行特性判断分组
                        var version = method.DeclaringType!.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
                        if (version.Any())
                        {
                            return version.Any(v => v == docName);
                        }
                        //这里获取action的特性
                        var actionVersion = method.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
                        if (actionVersion.Any())
                        {
                            return actionVersion.Any(v => v == docName);
                        }
                        return docName== nomarl;
                    });

                    options.CustomSchemaIds(type => type.FullName);
                    options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "LF.Application.xml"));
                    //JWT 认证配置
                    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                    {
                        Description = "在下框中输入请求头中需要添加Jwt授权Token：Bearer Token",
                        Name = "Authorization",
                        In = ParameterLocation.Header,
                        Type = SecuritySchemeType.ApiKey,
                        BearerFormat = "JWT",
                        Scheme = "Bearer"
                    });
                    options.AddSecurityRequirement(new OpenApiSecurityRequirement
                    {
                        {
                            new OpenApiSecurityScheme
                            {
                                Reference = new OpenApiReference {
                                    Type = ReferenceType.SecurityScheme,
                                    Id = "Bearer"
                                }
                            },
                            new string[] { }
                        }
                    });
                    }
                );
                Configure<AbpExceptionHandlingOptions>(options =>
                {
                    options.SendExceptionsDetailsToClients = true;
                });
            }
            #endregion

            #region JWT
            var jwt = config.GetSection("jwtAuth");
            services.Configure<Jwt>(jwt);

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options =>
            {
                LFConfig.Jwt = jwt.Get<Jwt>();
                options.RequireHttpsMetadata = false;
                options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateLifetime = true,
                    ValidateIssuer = true,
                    ValidateIssuerSigningKey = true,
                    ValidateAudience = true,
                    ValidAudience = jwt.GetValue<string>("audience"),
                    ValidIssuers = new string[] { jwt.GetValue<string>("issuer") },
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwt.GetValue<string>("securityKey")))
                };

                //// 添加事件处理以便于调试
                //options.Events = new JwtBearerEvents
                //{
                //    OnMessageReceived = context =>
                //    {
                //        var authHeader = context.Request.Headers["Authorization"].FirstOrDefault();
                //        Console.WriteLine($"收到Authorization头: {authHeader}");
                //        return Task.CompletedTask;
                //    },
                //    OnTokenValidated = context =>
                //    {
                //        Console.WriteLine("令牌验证成功");
                //        var claims = context.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
                //        foreach (var claim in claims)
                //        {
                //            Console.WriteLine($"Claim: {claim}");
                //        }
                //        return Task.CompletedTask;
                //    },
                //    OnAuthenticationFailed = context =>
                //    {
                //        Console.WriteLine($"令牌验证失败: {context.Exception.Message}");
                //        return Task.CompletedTask;
                //    }
                //};
            });
            #endregion

            #region 跨域白名单
            var cors = config.GetSection("cors").Get<string[]>();
            services.AddCors(options =>
                options.AddPolicy(
                    name: _orgins,
                    policy => policy.WithOrigins(cors)
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                )
            );
            #endregion

            Configure<AbpAspNetCoreMvcOptions>(options =>
            {
                options
                    .ConventionalControllers
                    .Create(typeof(LFModule).Assembly, opts =>
                    {
                        opts.RootPath = "LF";
                    });
            });

            #region 文件上传大小限制配置
            // 配置 IIS 相关的文件上传限制
            services.Configure<IISServerOptions>(options =>
            {
                options.MaxRequestBodySize = null; // 移除 IIS 限制
            });

            // 配置 Kestrel 文件上传限制
            services.Configure<KestrelServerOptions>(options =>
            {
                options.Limits.MaxRequestBodySize = null; // 移除 Kestrel 限制，允许无限大小
            });

            // 配置 FormOptions 文件上传限制
            services.Configure<FormOptions>(options =>
            {
                options.ValueLengthLimit = int.MaxValue; // 表单值长度限制
                options.MultipartBodyLengthLimit = long.MaxValue; // 多部分正文长度限制  
                options.MultipartHeadersLengthLimit = int.MaxValue; // 多部分标头长度限制
                options.MemoryBufferThreshold = int.MaxValue; // 内存缓冲区阈值
            });
            #endregion

        }
    }
}

